//-----------------------------------------------------------------------------
// Bend2D - Physics Engine
// Roberto Bender <beto.bender@gmail.com>
// Description: 
// Date: 21/03/2010
//-----------------------------------------------------------------------------
#include "collidable.h"
#include "moveable.h"
#include "bmath.h"
#include "factory.h"
using namespace bend2d;

Collidable::Collidable() :
    m_MoveableCast(NULL),
    m_CollisionHandler(NULL)
{
}

Collidable::CollidableList::iterator& Collidable::GetCollidableIterator()
{
    return m_Iterator;
}

bool Collidable::CanCollide(Collidable* object)
{
    switch(this->GetGeometricForm())
    {
        case CollidableForm::eMovingPoint:
            switch(object->GetGeometricForm())
            {
                case CollidableForm::eLine:
                    return CanCollideMovingPointWithStaticLine(this, object);
                case CollidableForm::eMovingPoint:
                    return CanCollideMovingPointWithMovingPoint(this, object);
                default:
                    break;
            }
            break;
        case CollidableForm::eLine:
            switch(object->GetGeometricForm())
            {
                case CollidableForm::eMovingPoint:
                    return CanCollideMovingPointWithStaticLine(object, this);
                default:
                    break;
            }

        default:
            break;
    }

    return false;
}

void Collidable::Collide(Collidable* object)
{
    if(m_CollisionHandler == NULL)
        m_CollisionHandler = Factory::GetInstance()->AccessObjectCreator()->AccessCollisionHandler();

    switch(this->GetGeometricForm())
    {
        case CollidableForm::eMovingPoint:
            switch(object->GetGeometricForm())
            {
                case CollidableForm::eLine:
                    m_CollisionHandler->CollideMovingPointWithStaticLine(this, object);
                    break;
                case CollidableForm::eMovingPoint:
                    m_CollisionHandler->CollideMovingPointWithMovingPoint(this, object);
                    break;
                default:
                    break;
            }
            break;
        case CollidableForm::eLine:
            switch(object->GetGeometricForm())
            {
                case CollidableForm::eMovingPoint:
                    m_CollisionHandler->CollideMovingPointWithStaticLine(object, this);
                default:
                    break;
            }
            break;
        default:
            break;
    }
}


bool Collidable::CanCollideMovingPointWithStaticLine(Collidable* movingPoint, Collidable* staticLine)
{
    Line myDetectionLine = movingPoint->GetMovingLine();
    Line objDetectionLine = staticLine->GetStaticLine();
    return Math::Cross(myDetectionLine, objDetectionLine, movingPoint->m_CollisionPoint);
}

bool Collidable::CanCollideMovingPointWithMovingPoint(Collidable* movingPointA, Collidable* movingPointB)
{
    Line myDetectionLine = movingPointA->GetMovingLine();
    Line againstMyDetectionLine = movingPointB->GetMovingLine();
    return Math::Cross(myDetectionLine, againstMyDetectionLine, movingPointA->m_CollisionPoint);
}

